package com.bianmaba.spring.data.jpa.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 业务类基础服务类
 * 此类配置了事务支持，并且事务回滚扩大到Exception异常（原为RuntimeException）
 * 注：mysql数据库必须是innoDB支持，并且表必须是innoDB
 * 使用实体自动生成表时，注意hibernate的dialect必须是org.hibernate.dialect.MySQL5InnoDBDialect
 */
@Transactional(rollbackFor = {Exception.class})
public abstract class BaseService<T, ID extends Serializable> implements IBaseService<T, ID> {

    protected Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Override
    public <S extends T> S save(S entity) {
        return getRepository().save(entity);
    }

    @Override
    public <S extends T> S saveAndFlush(S entity) {
        return getRepository().saveAndFlush(entity);
    }


    @Override
    public <S extends T> List<S> save(Iterable<S> entities) {
        return getRepository().saveAll(entities);
    }


    @Override
    public void delete(ID id) {
        getRepository().deleteById(id);
    }

    @Override
    public void delete(ID[] ids) {
        if (ids != null) {
            for (ID id : ids) {
                getRepository().deleteById(id);
            }
        }
    }

    @Override
    public void delete(T entity) {
        getRepository().delete(entity);
    }

    @Override
    public void delete(Iterable<? extends T> entities) {
        getRepository().deleteAll(entities);
    }

    @Override
    public void deleteAll() {
        getRepository().deleteAll();
    }

    @Override
    public void deleteInBatch(Iterable<T> entities) {
        getRepository().deleteInBatch(entities);
    }

    @Override
    public void deleteAllInBatch() {
        getRepository().deleteAllInBatch();
    }


    @Override
    public T getOne(ID id) {
        return getRepository().getOne(id);
    }

    @Override
    public T findOne(ID id) {
        Optional<T> optional = getRepository().findById(id);
        if (optional != Optional.empty()) {
            return optional.get();
        }
        return null;
    }


    @Override
    public <S extends T> S findOne(Example<S> example) {
        Optional<S> optional = getRepository().findOne(example);
        if (optional != Optional.empty()) {
            return optional.get();
        }
        return null;
    }


    public List<T> query() {
        return getRepository().findAll();
    }

    public List<T> all() {
        return getRepository().findAll();
    }

    @Override
    public List<T> query(Iterable<ID> ids) {
        return getRepository().findAllById(ids);
    }

    @Override
    public Iterable<T> query(Sort sort) {
        return getRepository().findAll(sort);
    }


    //-----------------查询，返回Page---------------
    @Override
    public Page<T> query(Pageable pageable) {
        return getRepository().findAll(pageable);
    }


    @Override
    public Page<T> query(String property, Object val) {
        return getRepository().findAll(property, val);
    }

    @Override
    public Page<T> query(String property, Object val, Pageable pageable) {
        return getRepository().findAll(property, val, pageable);
    }

    @Override
    public Page<T> query(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAll(params, pageable);
    }


    //-----------------去重查询，返回Page---------------
    @Override
    public Page<T> queryDistinct(String property, Object val) {
        return getRepository().findAllDistinct(property, val);
    }

    @Override
    public Page<T> queryDistinct(String property, Object val, Pageable pageable) {
        return getRepository().findAllDistinct(property, val, pageable);
    }

    @Override
    public Page<T> queryDistinct(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAllDistinct(params, pageable);
    }

    //-----------------查询，返回List---------------
    @Override
    public List<T> queryToList(String property, Object val) {
        return getRepository().findAllToList(property, val);
    }

    @Override
    public List<T> queryToList(String property, Object val, Pageable pageable) {
        return getRepository().findAllToList(property, val, pageable);
    }

    @Override
    public List<T> queryToList(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAllToList(params, pageable);
    }

    @Override
    @Deprecated
    public List<T> queryForList(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAllToList(params, pageable);
    }

    //-----------------去重查询，返回List---------------
    @Override
    public List<T> queryDistinctToList(String property, Object val) {
        return getRepository().findAllDistinctToList(property, val);
    }

    @Override
    public List<T> queryDistinctToList(String property, Object val, Pageable pageable) {
        return getRepository().findAllDistinctToList(property, val, pageable);
    }

    @Override
    public List<T> queryDistinctToList(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAllDistinctToList(params, pageable);
    }

    @Override
    @Deprecated
    public List<T> queryDistinctForList(Map<String, Object> params, Pageable pageable) {
        return getRepository().findAllDistinctToList(params, pageable);
    }

    @Override
    public <S extends T> Iterable<S> query(Example<S> example) {
        return getRepository().findAll(example);
    }

    @Override
    public <S extends T> Iterable<S> query(Example<S> example, Sort sort) {
        return getRepository().findAll(example, sort);
    }


    @Override
    public <S extends T> Page<S> query(Example<S> example, Pageable pageable) {
        return getRepository().findAll(example, pageable);
    }


    @Override
    public boolean exists(ID id) {
        return getRepository().existsById(id);
    }

    @Override
    public <S extends T> boolean exists(Example<S> example) {
        return getRepository().exists(example);
    }


    @Override
    public long count() {
        return getRepository().count();
    }

    @Override
    public <S extends T> long count(Example<S> example) {
        return getRepository().count(example);
    }


    @Override
    public void flush() {
        getRepository().flush();
    }

    @Override
    public void clear() {
        getRepository().clear();
    }

    @Override
    public void close() {
        getRepository().close();
    }

    @Override
    public void detach(Object obj) {
        getRepository().detach(obj);
    }

    @Override
    public void refresh(Object obj) {
        getRepository().refresh(obj);
    }
}
